<?php

namespace blog\admin\controller;

use think\Controller;
use think\Session;
use think\Cookie;

class Pub extends Controller
{
    public function logout()
    {
        if (Session::has('auth'))
            Session::destroy();
        return json_return("退出成功!", url('home/index/index'));
    }

    static public function chkLogin()
    {
        if (Session::has('auth'))
            return true;

        if (!Cookie::has('remember'))
            return false;

        $auth = unserialize(base64_decode(Cookie::get('remember')));
        Session::set('auth', $auth);

        return true;
    }

    public function login()
    {
        if (self::chkLogin())
            $this->redirect('Index/index');

        if ($this->request->isPost()) {

            $msg = $this->validate($_POST, [
                        'username|用户名' => 'require',
                        'password|密码' => 'require',
                        'captcha|验证码'=>'require|captcha'
                    ]);
            if ($msg !== true)
                return json_return($msg, null, null, null, 'ref_captcha();');

            $pwd = md5(md5($_POST['password']));

            $sql = sprintf('select id,name,role from bg_user where name="%s" and password="%s"', $_POST['username'], $pwd);
            $usr = sqlRow($sql);
            if (count($usr) == 0)
                return json_return('用户名或密码错误!');

            if (isset($_POST['remember']))
                Cookie::set('remember', base64_encode(serialize($usr)), 30);
            Session::set('auth', $usr);

            return json_return('登录成功!', url('Index/index'));
        }
        $this->assign('close_nav', true);
        $this->assign('close_bread', true);
        $this->assign('title', '登录系统');
        return $this->fetch();
    }


    public function password($id, $u, $t, $k)
    {
        $usr = sqlRow('select password,'.$t.' from bg_user where id='.$id);
        $key = $this->_forgetKey($id, $u, $usr['password'], $usr[$t]);
        if ($key != $k)
            return json_return('非法操作!', url('login'));

        if ($this->request->isPost()) {
            $msg = $this->validate($_POST, [
                'verify|验证密码'  => 'require|length:6,30',
                'pwd|密码'  => 'require|length:6,30',
               ]);
            if ($msg !== true) return json_return($msg);

            if ($_POST['verify'] !== $_POST['pwd'])
                return json_return('两次输入的密码不一致!');

            $pwd = md5(md5($_POST['pwd']));

            $ret = \think\Db::table('bg_user')
                ->where('id', $_POST['uid'])
                ->update(['password' => $pwd]);
            if (!$ret)
                return json_return('密码修改失败!');

            return json_return('密码修改成功!', url('login'));
        }

        $this->assign('url', $this->request->url());
        $this->assign('name', $u);
        $this->assign('uid', $id);
        return view();
    }

    //生成忘记密码验证数据的key
    private function _forgetKey($uid, $username, $password, $findtool)
    {
        return sha1($uid.md5($password).md5($username).md5($findtool));
    }

    //忘记密码刷新验证码返回函数封装
    private function _fgReturn($msg, $callback = null, $opt = [])
    {
        $callback = 'ref_captcha();'.($callback ?? '');
        $tag = $opt['tag'] ?? null;
        $url = $opt['url'] ?? null;
        $close = $opt['close'] ?? null;

        return json_return($msg, $url, $tag, $close, $callback);
    }

    //忘记密码流程第一步，字段正确性检查
    private function _forgetCheck()
    {
        //手机号码与邮箱验证及找回密码方式自动判断
        $ret = $this->validate(['findtool' => $_POST['findtool']],
                        ['findtool' => 'email']);
        $findtype = ($ret === true) ? 'email' : 'phone';
        if ($findtype === 'phone') {
            $ret = preg_match('/^[1][34578][0-9]{9}$/', $_POST['findtool']);
            if ($ret == 0)
                return '手机号码输入有误!';
        }

        //判断用户名与手机号或邮箱是否匹配
        $sql = sprintf('select id,password from bg_user where name="%s"'
                .' and %s="%s"', $_POST['username'], $findtype,
                $_POST['findtool']);
        $user = sqlRow($sql);
        if ($user === false)
            return '输入用户名与邮箱或手机不匹配!';

        $user['type'] = $findtype;

        return $user;
    }

    //忘记密码流程第二步，生成验证码和发送验证码
    private function _forgetSend($sesskey, $usr)
    {
        //生成验证码发送手机短信或邮箱
        $code = mt_rand(1000, 9999);
        if ($usr['type'] == 'email') {
            $ret = send_mail($_POST['findtool'], '博客系统找回密码的验证码', '验证码: <span style="color:red;font-weight:blod;font-size:24px">'.$code.'</span>');
        } else {
            $ret = aliyun_sms_send($_POST['findtool'], $code);
        }
        if ($ret === false)
            return $this->_fgReturn('发送失败，请检查手机号或邮箱地址是否正确!');

        //发送成功则保存手机或邮箱验证码等待下次提交来验证
        session($sesskey.'.code', $code);
        session($sesskey.'.time', time());
        session($sesskey.'.err', 0);
        session($sesskey.'.user', $_POST['username']);
        session($sesskey.'.tool', $_POST['findtool']);
        $url = 'id='.$usr['id'].'&u='.$_POST['username'].'&t='.$usr['type'];
        $url .= '&k='.$this->_forgetKey($usr['id'],
                $_POST['username'], $usr['password'], $_POST['findtool']);
        session($sesskey.'.url', $url);

        return $this->_fgReturn('发送成功, 请到邮箱或手机查看填写提交!',
                                'step_code();');
    }

    private function _forgetExpire($sesskey, $expire = 300)
    {
        if (time() - session($sesskey.'.time') >= $expire) {
            session($sesskey.'.code', null);
            session($sesskey.'.user', null);
            session($sesskey.'.tool', null);
            session($sesskey.'.time', null);
            session($sesskey.'.url', null);
            return true;
        }
        return false;
    }

    //忘记密码流程第三步，验证收到手机或邮箱验证码
    private function _forgetVerify($sesskey)
    {
        //判断session里是否保存code值，如果存在代表已经完成忘记密码第一步
        if (!session('?'.$sesskey.'.code')
                || !session('?'.$sesskey.'.time')
                || !session('?'.$sesskey.'.url')
                || !session('?'.$sesskey.'.err')
                || $this->_forgetExpire($sesskey))
            return false;

        $err = session($sesskey.'.err');
        if ($err >= 5) {
            $min =(int)((300 - (time() - session($sesskey.'.time'))) / 60);
            return $this->_fgReturn('你验证次数太多了，请等待'.$min.'分钟后再试!');
        }

        //判断手机或邮箱验证码是否存在并且不能为空
        if (!isset($_POST['code']) || $_POST['code'] === '')
            return $this->_fgReturn('请输入手机或邮箱验证码!', 'step_code();');

        if (session($sesskey.'.code') != $_POST['code']) {
            session($sesskey.'.err', ++$err);
            return $this->_fgReturn('手机或邮箱验证码验证失败，请检查重输入!');
        }

        $url = url('password', session($sesskey.'.url'));
        $pop = 'kyo_pop(\'"url": "'.$url.'", "w": 500, "h": 300, "title": "修改密码", "bc": "forget_close();"\')';
        session($sesskey.'.code', null);
        session($sesskey.'.user', null);
        session($sesskey.'.tool', null);
        session($sesskey.'.time', null);
        session($sesskey.'.url', null);
        return $this->_fgReturn('', $pop);
    }

    public function forget()
    {
        if ($this->request->isPost()) {
            //验证字段是否为空或长度验证
            $msg = $this->validate($_POST, [
                'username|用户名'  => 'require|length:2,30',
                'findtool|邮箱或手机'  => 'require|length:6,30',
                'captcha|验证码'=>'require|captcha',
               ]);
            if ($msg !== true) return $this->_fgReturn($msg);

            $sesskey = md5('forget'.$_POST['username'].$_POST['findtool']);

            $json = $this->_forgetVerify($sesskey);
            if ($json !== false) return $json;

            $msg = $this->_forgetCheck();
            if (!is_array($msg)) return $this->_fgReturn($msg);

            return $this->_forgetSend($sesskey, $msg);
        }

        $this->assign('close_nav', true);
        $this->assign('close_bread', true);
        $this->assign('title', '找回密码');
        // dump(\think\Session::get());
        return $this->fetch();
    }
}

